package config;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Vector;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import core.Recurso;



public class RecursoXmlHandler implements IRecursoHandler {

	private static String RECURSO_XML_FILENAME = "recursos.xml";
	private File recursosXml;
	private static final String ROOT = "recursos";
	
	public RecursoXmlHandler(String serverName) throws ConfigurationException {
		try {
			//cria um diretorio de configuracao com o nome do servidor
			File configDir = new File(serverName);
			if (!configDir.exists()){
				configDir.mkdir();
			}

			//cria o arquivo de configuração no diretório com nome do servidor
			this.recursosXml = new File(configDir, RECURSO_XML_FILENAME);
			if (!this.recursosXml.exists()) {
				this.recursosXml.createNewFile();
				create();
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new ConfigurationException("Erro ao manipular arquivo " + this.recursosXml + ".", e);
		}
	}
	
	private Document read() throws ConfigurationException {
		try{
			SAXBuilder saxBuilder = new SAXBuilder();
			
			Document document = saxBuilder.build(this.recursosXml);
			
			//se o arquivo não contém elementos, cria uma nova estrutura
			if (document.getContentSize() == 0){
				create();
			}
			
			return document;
		
		} catch (IOException e) {
			e.printStackTrace();
			throw new ConfigurationException("Erro ao manipular arquivo " + this.recursosXml + ".", e);
		} catch (JDOMException e) {
			e.printStackTrace();
			throw new ConfigurationException("JDOM Error.", e);
		} 
	}
	
	private void create() throws ConfigurationException {
		Document document = new Document();
		document.setRootElement(new Element(ROOT));
		
		save(document);
	}
	
	private void save(Document document) throws ConfigurationException{
		try {
			Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.recursosXml, false), "UTF8"));
	
			XMLOutputter xmlOutputter = new XMLOutputter();
			xmlOutputter.output(document, writer);
		
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw new ConfigurationException("Encoding UTF8 não suportado.", e);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new ConfigurationException("Arquivo " + this.recursosXml + " não encontrado.", e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new ConfigurationException("Erro ao manipular arquivo " + this.recursosXml + ".", e);
		}
	}
	
	@Override
	public void addRecurso(Recurso recurso) throws ConfigurationException{
		Document document = read();
		Element root = document.getRootElement();

		//insere no documento apenas se já não existir um elemento com o mesmo nome
		if (root.getChild(recurso.getNome()) == null){
			Element child = new Element(recurso.getNome());
			Element descricao = new Element(Recurso.DESCRICAO);
			Element maquina = new Element(Recurso.MAQUINA);
			Element local = new Element(Recurso.LOCAL);
			
			descricao.setText(recurso.getDescricao());
			maquina.setText(recurso.getMaquina());
			local.setText(recurso.getLocal());
			
			child.addContent(0, descricao);
			child.addContent(1, maquina);
			child.addContent(2, local);
			
			root.addContent(child);
			
			save(document);
		}
		
	}

	@Override
	public void modifyRecurso(Recurso recurso) throws ConfigurationException{
		Document document = read();
		Element root = document.getRootElement();
		
		Element child = root.getChild(recurso.getNome());
		Element.class.cast(child.getContent(0)).setText(recurso.getDescricao());
		Element.class.cast(child.getContent(1)).setText(recurso.getMaquina());
		Element.class.cast(child.getContent(2)).setText(recurso.getLocal());
	
		save(document);
	}

	@Override
	public void removeRecurso(Recurso recurso) throws ConfigurationException{
		Document document = read();
		Element root = document.getRootElement();
		
		root.removeChild(recurso.getNome());
		
		save(document);
	}

	@Override
	public Vector<Recurso> listRecursos() throws ConfigurationException {
		Document document = read();
		Element root = document.getRootElement();
		
		Vector<Recurso> recursos = new Vector<Recurso>();
		
		for (Object object : root.getChildren()){
			Element element = (Element) object;
			
			Recurso recurso = new Recurso();
			recurso.setNome(element.getName());
			recurso.setDescricao(element.getContent(0).getValue());
			recurso.setMaquina(element.getContent(1).getValue());
			recurso.setLocal(element.getContent(2).getValue());
			
			recursos.add(recurso);
		}
		
		return recursos;
	}
	
}
